package com.rslai.base.tool.servertest.command;

import com.rslai.base.tool.autotest.mock.util.JSON;
import com.rslai.base.tool.servertest.context.Context;
import com.rslai.base.tool.servertest.exception.ExecuteException;
import com.rslai.base.tool.servertest.model.KeyValueStore;
import com.rslai.base.tool.servertest.response.Response;
import com.rslai.base.tool.servertest.util.CloneUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;

public class AssertStepCommand extends ParameterizedCommand {
    private static final String separator = System.getProperty("line.separator", "\r\n");

    private String error = "";
    private String desc;

    public AssertStepCommand(List<KeyValueStore> params, String desc) {
        super(params);
        this.desc = desc;
    }

    protected Response doExecuteInternal(Response preResult, List<KeyValueStore> processedParams, Context context) throws Throwable {
        Map expectation = convertKeyValueStoreToMap(processedParams);
        try {
            this.logger.info("assert command<{}> is starting... ", expectation);
            preResult.verify(expectation);
            return preResult;
        } catch (Exception e) {
            String message = "assert step invoke has error,expect=" + expectation + separator + "result=" + preResult;
            this.logger.error(message, e);
            this.error = JSON.toJSONString(preResult);
            throw new ExecuteException(message, e);
        }
    }

    public StepCommand doClone() {
        return new AssertStepCommand(CloneUtil.cloneKeyValueStore(this.params), this.desc);
    }

    public Map<String, Object> toReport() {
        Map details = new HashMap();
        details.put("stepName", String.format("验证:%s", new Object[]{this.desc}));
        List params = new ArrayList();
        params.addAll(this.params);

        params.add(new KeyValueStore("实际值", this.error));

        details.put("params", params);
        return details;
    }

    private Map<String, String> convertKeyValueStoreToMap(List<KeyValueStore> params) {
        Map result = new HashMap();
        for (KeyValueStore kvs : params) {
            Object value = kvs.getValue();
            if ((value instanceof Map))
                result.putAll((Map) value);
            else {
                result.put(kvs.getName(), (String) value);
            }
        }
        return result;
    }
}
